
// Copyright (c) WanSheng Intelligent Corp. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.


#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include "wa_edge_types.h"
#include "wa_alarm.h"
#include "cJSON.h"
#include "logs.h"


void init_alarm(iagent_alarm_t* alarm, 
        unsigned int alarm_id,
        severity_t severity,
        object_type_t target_type,
        const char * target_id,
        const char * title,
        const char * content)
{
    memset(alarm, 0, sizeof(*alarm));
    alarm->alarm_id = alarm_id;
    alarm->severity = severity;
    alarm->obj_type = target_type;
    strncpy(alarm->obj_id, target_id, sizeof(alarm->obj_id)-1);
    if(title) strncpy(alarm->title, title, sizeof(alarm->title)-1);
    if(content) strncpy(alarm->content, content, sizeof(alarm->content)-1);
    time(&alarm->alarm_time);
    alarm->alarm_status = EVT_ALARM_SET;
}

static void  set_alarm_JSON(cJSON* j_alarm,
        unsigned int alarm_id,
        const char * title,
        object_type_t target_type,
        const char * target_id,
        const char * group,
        const char * content,
        time_t start,
        time_t end,
        alarm_status_t alarm_status,
        severity_t severity,
        const char * clear_reason
        )
{
    cJSON_AddNumberToObject(j_alarm, "alarmid", alarm_id);
    cJSON_AddStringToObject(j_alarm, "title", title);
    cJSON_AddStringToObject(j_alarm, "targetid", target_id);
    cJSON_AddNumberToObject(j_alarm, "targettype", target_type);
    cJSON_AddStringToObject(j_alarm, "content", content);
    cJSON_AddStringToObject(j_alarm, "group", group);
    cJSON_AddStringToObject(j_alarm, "clear_reason", clear_reason?clear_reason:"");
    cJSON_AddNumberToObject(j_alarm, "set_t", start);
    cJSON_AddNumberToObject(j_alarm, "clear_t", end);
    cJSON_AddNumberToObject(j_alarm, "severity", severity);

    if(alarm_status == EVT_ALARM_SET)
    {
        cJSON_AddStringToObject(j_alarm, "status", "ACTIVE");
    }
    else if(alarm_status == EVT_ALARM_CLEAR)
    {
        cJSON_AddStringToObject(j_alarm, "status", "CLEARED");
    }
}    





char * clear_alarm_payload_A(unsigned int alarm_id, 
    object_type_t target_type, const char * target_id, 
    const char * clear_reason)
{
    cJSON *payload_obj;
    char *payload = NULL;
    payload_obj = cJSON_CreateObject();

    cJSON_AddNumberToObject(payload_obj, "alarmid", alarm_id);
    cJSON_AddStringToObject(payload_obj, "targetid", target_id);
    cJSON_AddNumberToObject(payload_obj, "targettype", target_type);
    cJSON_AddStringToObject(payload_obj, "clear_reason", clear_reason?clear_reason:"");

    payload = cJSON_Print(payload_obj);
    cJSON_Delete(payload_obj);
    return payload;
}


void single_alarm_to_JSON(iagent_alarm_t* alarm, cJSON * elem)
{
    set_alarm_JSON(elem, 
        alarm->alarm_id,
        alarm->title,
        alarm->obj_type,
        alarm->obj_id,
        alarm->group,
        alarm->content,
        alarm->alarm_time,
        alarm->clear_time,
        alarm->alarm_status,
        alarm->severity,
        alarm->clear_reason);
}


char* serialize_single_alarm(iagent_alarm_t* alarm)
{
    cJSON * root = cJSON_CreateObject();
    single_alarm_to_JSON(alarm, root);
    char * text = cJSON_Print(root);
    cJSON_Delete(root);
    return text;
}


char* serialize_alarms_A( iagent_alarm_t * alarms, int num)
{
    cJSON * root = cJSON_CreateArray();

    for(int i=0; i<num; i++)
    {
        cJSON * elem = cJSON_CreateObject();
        single_alarm_to_JSON(&alarms[i], elem);
        cJSON_AddItemToArray(root, elem);
    }
    char * payload = cJSON_Print(root);
    cJSON_Delete(root);
    return payload;
}


bool parse_single_alarm(cJSON * item, iagent_alarm_t * alarm)
{
    if(item->type != cJSON_Object)
        return false;

    memset(alarm, 0, sizeof(*alarm));
    
    cJSON * e = cJSON_GetObjectItem(item, "targettype");
    if(!cJSON_IsNumber(e))
        return false;
    alarm->obj_type = (object_type_t) e->valueint;

    e = cJSON_GetObjectItem(item, "targetid");
    if(e == NULL || e->type != cJSON_String)
        return false;
    strncpy(alarm->obj_id, e->valuestring, sizeof(alarm->obj_id)-1);

    e = cJSON_GetObjectItem(item, "alarmid");
    if(e == NULL || e->type != cJSON_Number)
        return false;
    alarm->alarm_id = e->valuedouble;

    // end of mandatory fields

    e = cJSON_GetObjectItem(item, "severity");
    if(e != NULL && e->type == cJSON_Number)
        alarm->severity = e->valuedouble;


    e = cJSON_GetObjectItem(item, "clear_t");
    if(e != NULL && e->type == cJSON_Number)
        alarm->clear_time = e->valuedouble;

    e = cJSON_GetObjectItem(item, "set_t");
    if(e != NULL && e->type == cJSON_Number)
        alarm->alarm_time = e->valuedouble;

    alarm->alarm_status = EVT_ALARM_UNDEFINED;
    e = cJSON_GetObjectItem(item, "title");
    if(e != NULL && e->type == cJSON_String)
        strncpy(alarm->title, e->valuestring, sizeof(alarm->title)-1);

    e = cJSON_GetObjectItem(item, "content");
    if(e != NULL && e->type == cJSON_String)
        strncpy(alarm->content, e->valuestring, sizeof(alarm->content)-1);

    e = cJSON_GetObjectItem(item, "group");
    if(e != NULL && e->type == cJSON_String)
        strncpy(alarm->group, e->valuestring, sizeof(alarm->group)-1);

    e = cJSON_GetObjectItem(item, "clear_reason");
    if(e != NULL && e->type == cJSON_String)
        strncpy(alarm->clear_reason, e->valuestring, sizeof(alarm->clear_reason)-1);

    alarm->alarm_status = EVT_ALARM_UNDEFINED;
    e = cJSON_GetObjectItem(item, "status");
    if(e != NULL && e->type == cJSON_String)
    {    
        if(strcmp(e->valuestring, "ACTIVE"))
        {
            alarm->alarm_status = EVT_ALARM_SET;

        }
        else if(strcmp(e->valuestring, "CLEARED"))
        {
            alarm->alarm_status = EVT_ALARM_CLEAR;
        }
    }
    if(alarm->clear_time && alarm->alarm_status == EVT_ALARM_UNDEFINED)
        alarm->alarm_status = EVT_ALARM_CLEAR;

    return true;
}


int parse_alarm_payload_A(char * payload, int payload_len, iagent_alarm_t ** alarms_out)
{
    int cnt = 0;
    iagent_alarm_t * alarms = NULL;
    cJSON * root = cJSON_ParseWithLength(payload, payload_len);
    if(root == NULL)
        return false;

    if(root->type == cJSON_Object)
    {
        alarms = (iagent_alarm_t*) malloc(sizeof(iagent_alarm_t));
        if(parse_single_alarm(root, alarms))
            cnt = 1;

        goto end;
    }
    else if(root->type == cJSON_Array)
    {
        cJSON * elem;
        alarms = (iagent_alarm_t*) malloc(sizeof(iagent_alarm_t)*cJSON_GetArraySize(root));
        if(alarms == NULL)
        {
            goto end;
        }
        cJSON_ArrayForEach(elem, root)
        {
            if(parse_single_alarm(elem, alarms+cnt))
            {
                cnt ++;
            }
        }
    }
    else
    {
        WARNING2("invalid alarm payload");
    }
end:
    cJSON_Delete(root);
    *alarms_out = alarms;
    return cnt;
}